package com.fnzn.entranceGuard.rest.usrCloud;

import cn.usr.UsrCloudMqttCallbackAdapter;
import cn.usr.UsrCloudMqttClientAdapter;
import com.fnzn.entranceGuard.constant.DeviceConstant;
import com.fnzn.entranceGuard.constant.GuardConstant;
import com.fnzn.entranceGuard.entity.GuardDevice;
import com.fnzn.entranceGuard.entity.GuardDeviceRecord;
import com.fnzn.entranceGuard.entity.power.PowerBase;
import com.fnzn.entranceGuard.entity.ths.ThsBase;
import com.fnzn.entranceGuard.rest.guard.UsrUtil;
import com.fnzn.entranceGuard.service.IGuardDeviceRecordService;
import com.fnzn.entranceGuard.service.IGuardDeviceService;
import com.fnzn.entranceGuard.service.IGuardIcDeviceService;
import com.fnzn.entranceGuard.service.IGuardQrInfoService;
import com.fnzn.entranceGuard.service.attendence.AttendanceRecordService;
import com.fnzn.entranceGuard.service.power.IPowerBaseService;
import com.fnzn.entranceGuard.service.ths.IThsBaseService;
import com.fnzn.entranceGuard.util.DateTools;
import com.fnzn.entranceGuard.util.QRGenerate;
import com.fnzn.entranceGuard.util.SpringUtil;
import com.fnzn.entranceGuard.util.StatusEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;

/**
 * @author wf_sxf@163.com
 * @date 2018/5/24 18:59
 */

public class ClinetCallbackAdapter extends UsrCloudMqttCallbackAdapter {

    Logger log = LoggerFactory.getLogger(ClinetCallbackAdapter.class);

    private boolean sub = false;


    //读头
    private final byte TYPE_SCAN = 0x01;
    //时钟
    private final byte TYPE_CLOCK = 0x02;
    //社区
    private final byte TYPE_COM = 0x03;
    //增加的回执信息
    private final byte TYPE_ADD = 0x04;
    //删除的回执信息
    private final byte TYPE_DEL = 0x05;
    //IC卡开门记录
    private final byte TYPE_IC = 0x06;
    //初始化设备
    private final byte TYPE_INIT = 0x07;
    //设备故障
    private final byte TYPE_BREAK = 0x08;

    /**
     * 连接回调
     *
     * @param returnCode
     * @param description
     */
    @Override
    public void onConnectAck(int returnCode, String description) {
        log.info("连接有人云回调：returnCode:" + returnCode + ",description:" + description);
        if (returnCode == 3 || returnCode == 1) {
            //断开连接
            sub = false;
            UsrUtil.clientAdapter = null;
            try {
                Thread.sleep(5000);
                log.error("断开连接，进行重连。");
                UsrUtil.getInstance();
            } catch (Exception e) {
                sub = false;
                e.printStackTrace();
            }
        } else if (returnCode == 2) {
            //连接成功，进行订阅
            //進行循環訂閲
            if (subscribe()) {
                log.info("订阅成功！");
            } else {
                log.error("訂閲失敗！");
            }
        }
        super.onConnectAck(returnCode, description);
    }

    public boolean subscribe() {
        int i = 0;
        //订阅失败的时候
        while (true) {
            try {

                //* 1.初始化客户端适配 *//*
                UsrCloudMqttClientAdapter clientAdapter = UsrUtil.getInstance();
                Thread.sleep(5000);
                clientAdapter.SubscribeForUsername();
                return true;
            } catch (Exception e) {
                i++;
                if (i % 5 == 5) {
                    //重置
                    UsrUtil.clientAdapter = null;
                }
                //失败
                log.error("订阅失败，", e);
                e.printStackTrace();
            }
            //return false;
        }
    }

    /**
     * 订阅回调
     *
     * @param messageId
     * @param clientId
     * @param topics
     * @param returnCode
     */
    @Override
    public void onSubscribeAck(int messageId, String clientId, String topics, int returnCode) {
        log.info("订阅（回调）：clientId:" + clientId + ",topics:" + topics + ",returnCode:" + returnCode);
        //订阅成功后，关闭循环
        if (returnCode == 0) {
            sub = true;
        }
    }

    /**
     * 取消订阅回调
     */
    @Override
    public void onDisSubscribeAck(int messageId, String clientId, String topics, int returnCode) {

    }

    /**
     * 推送相应 回调
     */
    @Override
    public void onPublishDataAck(int messageId, String topic, boolean isSuccess) {
        log.info("推送回调：topic:" + topic + ",isSuccess:" + isSuccess + ",messageId:" + messageId);
    }

    /**
     * 本次推送结果回调函数
     *
     * @param messageId
     * @param topic
     */
    @Override
    public void onPublishDataResult(int messageId, String topic) {
        log.info("推送结果：messageId:" + messageId + ",topic:" + topic);
    }

    /**
     * 收到数据 回调函数
     *
     * @param messageId
     * @param topic     $USR/DevTx/00012950000000000001
     * @param data      结构
     */
    @Override
    public void onReceiveEvent(int messageId, String topic, byte[] data) {
        log.info("接受数据:" + topic);
//        for (int i = 0; i < data.length; i++) {
//            System.out.print(Integer.toHexString(Integer.valueOf(data[i])));
//            System.out.print(" ");
//        }
        //System.out.println(data.length);
        try {
            //获取设备ID
            String deviceId = "";
            String[] topics = topic.split("/");
            if (topics.length > 2) {
                deviceId = topics[3];
            }
            //判断起始帧 FF为门禁
            if (QRGenerate.parse16Str2HexByte("FF")[0] == data[0]) {
                Integer dataLength = QRGenerate.parse16HexByteToInt(data[2]);
                Integer dataType = QRGenerate.parse16HexByteToInt(data[3]);
                //返回IC卡逻辑状态  0失败 1 成功
                Integer state;
                //返回所有的IC卡号（16进制byte）
                byte[] icIds;
                //解析请求类型
                IGuardIcDeviceService iGuardIcDeviceService = SpringUtil.getBean(IGuardIcDeviceService.class);
                switch (data[1]) {
                    case TYPE_SCAN:
                        IGuardQrInfoService qrService = SpringUtil.getBean(IGuardQrInfoService.class);
                        AttendanceRecordService recordService = SpringUtil.getBean(AttendanceRecordService.class);
                        //开门信息，记录到数据库
                        StringBuffer qrInfo = new StringBuffer();
                        for (int i = 0; i < dataLength; i++) {
                            if (i < 7 && i > 2) {
                                byte[] temp = new byte[4];
                                System.arraycopy(data, 7, temp, 0, 4);
                                qrInfo.append(QRGenerate.parse16Byte2Str(temp));
                                i = 6;
                            } else {
                                qrInfo.append(QRGenerate.parse16HexByte2Str(data[4 + i]));
                            }
                        }

                        //开门状态 第4+dataLength位
                        Integer status = QRGenerate.parse16HexByteToInt(data[4 + dataLength]);
                        //开门类型  1门禁 0电梯
                        Integer type = QRGenerate.parse16HexByteToInt(data[3]);
                        //根据二维码内容更新开门信息  1 200成功 2 300过期 0 403无权限
                        qrService.updateByContent(qrInfo.toString(), StatusEnum.getStatusByCode(status), StatusEnum.getDesByCode(status), type, deviceId);
                        //判断是否考勤
                        recordService.attendanceByQr(qrInfo.toString());
                        break;
                    case TYPE_CLOCK:
                        //返回时钟信息
                        UsrUtil.publishForDevId(UsrUtil.PublishFormat(getClock(), GuardConstant.TYPE_CLOCK), deviceId);
                        break;
                    case TYPE_COM:
                        UsrUtil.publishForDevId(UsrUtil.PublishFormat(getCom(deviceId), GuardConstant.TYPE_COM), deviceId);
                        break;
                    case TYPE_ADD:
                        //TODO 处理IC卡逻辑  state 状态 0失败 1 成功
                        state = QRGenerate.parse16HexByteToInt(data[4 + dataLength]);

                        icIds = new byte[dataLength];
                        System.arraycopy(data, 4, icIds, 0, dataLength);

                        iGuardIcDeviceService.updateStatus(deviceId, icIds, state);
                        break;
                    case TYPE_DEL:
                        //state 状态 0失败 1 成功
                        state = QRGenerate.parse16HexByteToInt(data[4 + dataLength]);
                        icIds = new byte[dataLength];
                        System.arraycopy(data, 4, icIds, 0, dataLength);

                        iGuardIcDeviceService.deleteIcDevice(deviceId, icIds, state);
                        break;
                    case TYPE_IC:
                        //打印IC出入记录  格式 设备ID,时间，IC卡号
                        StringBuilder sb = new StringBuilder();
                        sb.append(deviceId);
                        sb.append(",");
                        sb.append(DateTools.getCurrentSysData(DateTools.FULL_FORMAT));
                        sb.append(",");
                        icIds = new byte[4];
                        System.arraycopy(data, 4, icIds, 0, 4);
                        sb.append(QRGenerate.parse16Byte2Str(icIds));
                        IcLog.log(sb.toString());
                        break;
                    case TYPE_BREAK:
                        String message = QRGenerate.parse16HexByteToInt(data[4 + dataLength]).toString();
                        GuardDeviceRecord guardDeviceRecord = SpringUtil.getBean(GuardDeviceRecord.class);
                        IGuardDeviceRecordService iGuardDeviceRecordService = SpringUtil.getBean(IGuardDeviceRecordService.class);
                        guardDeviceRecord.setMessage(message);
                        guardDeviceRecord.setDeviceId(deviceId);
                        iGuardDeviceRecordService.addObj(guardDeviceRecord);
                        break;
                }
            }
            //电表起始值  ZNDB
            if (DeviceConstant.power_data[0] == data[0] && DeviceConstant.power_data[1] == data[1]
                    && DeviceConstant.power_data[2] == data[2] && DeviceConstant.power_data[3] == data[3]
                    //结束值 ZNDB
                    & DeviceConstant.power_data[0] == data[data.length - 4] && DeviceConstant.power_data[1] == data[data.length - 3]
                    && DeviceConstant.power_data[2] == data[data.length - 2] && DeviceConstant.power_data[3] == data[data.length - 1]
                    ) {
                IPowerBaseService baseService = SpringUtil.getBean(IPowerBaseService.class);
                PowerBase base = fillPowerData(data);
                base.setDeviceId(deviceId);
                baseService.uninUpdate(base);
            }
            //传感器起始值  THS
            if (DeviceConstant.ths_data[0] == data[0] & DeviceConstant.ths_data[1] == data[1]
                    & DeviceConstant.ths_data[2] == data[2]
                    //结束值 ZNDB
                    & DeviceConstant.ths_data[0] == data[data.length - 3] & DeviceConstant.ths_data[1] == data[data.length - 2]
                    & DeviceConstant.ths_data[2] == data[data.length - 1]
                    ) {
                /**
                 * 温湿度传感器
                 */
                IThsBaseService baseService = SpringUtil.getBean(IThsBaseService.class);
                ThsBase base = fillThsData(data);
                base.setDeviceId(deviceId);
                baseService.uninUpdate(base);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static ThsBase fillThsData(byte[] data) {
        //THS0000401033E015F00BA
        ThsBase base = new ThsBase();
        byte[] power = new byte[5];
        byte[] bytes = new byte[4];
        //传感器号
        System.arraycopy(data, 3, power, 0, 5);
        base.setPowerId(QRGenerate.AToString(power));
        //湿度
        System.arraycopy(data, 14, bytes, 0, 4);
        base.setHum(new BigDecimal(Integer.parseInt(QRGenerate.AToString(bytes), 16)).divide(new BigDecimal(10)));
        //温度
        System.arraycopy(data, 18, bytes, 0, 4);
        base.setTem(new BigDecimal(Integer.parseInt(QRGenerate.AToString(bytes), 16)).divide(new BigDecimal(10)));
        return base;
    }

    public Integer ascToInteger(byte b) {
        return Integer.parseInt((String.valueOf((char) b)), 16);
    }

    public static void main(String[] args) {
        byte[] bs = {0x54, 0x48, 0x53, 0x30, 0x30, 0x30, 0x30, 0x34, 0x30, 0x31, 0x30, 0x33, 0x33, 0x45, 0x30, 0x31, 0x35, 0x44, 0x30, 0x30, 0x42, 0x42, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x37, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x41, 0x44, 0x39, 0x43, 0x54, 0x48, 0x53};
        ThsBase b = fillThsData(bs);
    }

    public PowerBase fillPowerData(byte[] data) {
        PowerBase base = new PowerBase();
        byte[] power = new byte[5];
        byte[] bytes = new byte[4];
        //电表号
        System.arraycopy(data, 4, power, 0, 5);
        base.setPowerId(QRGenerate.AToString(power));
        //A项电压小数一位 16-19
        System.arraycopy(data, 15, bytes, 0, 4);
        base.setAU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //B项电压小数一位 20-23
        System.arraycopy(data, 19, bytes, 0, 4);
        base.setBU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //C项电压小数一位 24-27
        System.arraycopy(data, 23, bytes, 0, 4);
        base.setCU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //A项电流小数三位 28-31
        System.arraycopy(data, 27, bytes, 0, 4);
        base.setAI(tranferBigdecimal(bytes).divide(new BigDecimal(1000)));
        //B项电流小数三位 32-35
        System.arraycopy(data, 31, bytes, 0, 4);
        base.setBI(tranferBigdecimal(bytes).divide(new BigDecimal(1000)));
        //C项电流小数三位 36-39
        System.arraycopy(data, 35, bytes, 0, 4);
        base.setCI(tranferBigdecimal(bytes).divide(new BigDecimal(1000)));
        //总有功功率无小数单位W 40-43
        System.arraycopy(data, 39, bytes, 0, 4);
        base.setPower(tranferBigdecimal(bytes).intValue());
        //A相有功功率无小数单位W 44-47
        System.arraycopy(data, 43, bytes, 0, 4);
        base.setAPower(tranferBigdecimal(bytes).intValue());
        //B相有功功率无小数单位W 48-51
        System.arraycopy(data, 47, bytes, 0, 4);
        base.setBPower(tranferBigdecimal(bytes).intValue());
        //C相有功功率无小数单位W 52-55
        System.arraycopy(data, 51, bytes, 0, 4);
        base.setCPower(tranferBigdecimal(bytes).intValue());
        //A相线电压小数1位单位V 108-111
        System.arraycopy(data, 107, bytes, 0, 4);
        base.setALineU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //B相线电压小数1位单位V 112-115
        System.arraycopy(data, 111, bytes, 0, 4);
        base.setBLineU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //C相线电压小数1位单位V 116-119
        System.arraycopy(data, 115, bytes, 0, 4);
        base.setCLineU(tranferBigdecimal(bytes).divide(new BigDecimal(10)));
        //A相电压频率2位小数单位Hz 120-123
        System.arraycopy(data, 119, bytes, 0, 4);
        base.setAUFrequency(tranferBigdecimal(bytes).divide(new BigDecimal(100)));
        //B相电压频率2位小数单位Hz 124-127
        System.arraycopy(data, 123, bytes, 0, 4);
        base.setBUFrequency(tranferBigdecimal(bytes).divide(new BigDecimal(100)));
        //C相电压频率2位小数单位Hz 128-131
        System.arraycopy(data, 127, bytes, 0, 4);
        base.setCUFrequency(tranferBigdecimal(bytes).divide(new BigDecimal(100)));
        //有功总电量2位小数单位Kwh 132-140
        bytes = new byte[8];
        System.arraycopy(data, 131, bytes, 0, 8);
        base.setTotalPower(tranferBigdecimal(bytes).divide(new BigDecimal(100)));
        return base;
    }

    //根据ascii的16进制byte数组 转bigdecimal
    public static BigDecimal tranferBigdecimal(byte[] bytes) {
        return new BigDecimal(Integer.parseInt(QRGenerate.AToString(bytes), 16));
    }

    public static byte[] getClock() {
        //倒叙获取当前时间
        StringBuffer now = new StringBuffer(DateTools.getCurrentSysData("ssmmHHddMMyy"));
        //因为星期位数不确定所以去掉星期
        System.out.println("当前时间：" + now);
        now.insert(6, "01");
        return QRGenerate.parse16Str2HexByte(now.toString());
        //String m = now.substring(6, 9);
        //return  QRGenerate.parse16Str2HexByte(now.replace(m,WeekEnum.getNameByCode(m)));

    }

    /**
     * 根据设备号获取小区逻辑编号以及该社区下设备逻辑编号
     *
     * @param deviceId
     * @return byte[] 三位16进制数组
     * @throws Exception
     */
    public static byte[] getCom(String deviceId) throws Exception {
        IGuardDeviceService guardDeviceService = SpringUtil.getBean(IGuardDeviceService.class);
        //返回小区编号
        Integer communityCode = guardDeviceService.getCommunityCodeByDeviceId(deviceId);
        GuardDevice device = guardDeviceService.getDeviceCodeByDeviceId(deviceId);
        return UsrUtil.communityCodeFormat(communityCode, device);
    }

    public static String toStringHex1(String s) {
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
                        i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "ASCII");
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }
}
